package com.gopay.common.cipher.utils;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import com.gopay.common.cipher.constants.SensitiveInfoConstants;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 
 * @ClassName: KeyPropertiesUtils 
 * @Description: 敏感信息加解密算法中，操作配置文件
 * @author zyt 
 * @date 2016年11月23日 上午10:23:20
 */
public class KeyPropertiesUtils {

	private static Logger logger = LoggerFactory.getLogger(KeyPropertiesUtils.class);

	private static final String MASTERKEY_PATH = "mkey_path";

	//master key配置文件的绝对路径
	private static String MASTERKEY_ABSOLUTE_PATH;

	//默认master key配置文件的绝对路径
	private static final String DEFAULT_MASTERKEY_PATH = "/usr/local/ciecc/webapps/upload/sensitiveInfoKey/keys.properties";
	//private static final String DEFAULT_MASTERKEY_PATH = "D:/mkey/keys.properties";

	private static Properties getProp(){
		if(MASTERKEY_ABSOLUTE_PATH == null){
            loadProperiesPath();
		}
        try {
            InputStream inputstream = new BufferedInputStream(new FileInputStream(MASTERKEY_ABSOLUTE_PATH));
            Properties masterKeyProConfig = new Properties();
            masterKeyProConfig.load(inputstream);
            inputstream.close();
            return masterKeyProConfig;
        } catch (IOException e) {
            logger.error("获取密钥配置失败：", e);
            return null;
        }
	}
	
	/**
	 * 
	 * @Description: 	加载配置文件到内存 
	 * @author 			zyt
	 */
	private static void loadProperiesPath(){
        try {
			InputStream inputstream = KeyPropertiesUtils.class.getClassLoader().getResourceAsStream(SensitiveInfoConstants.CIPHERPROP_PATH);
			Properties pathConfig = new Properties();
			pathConfig.load(inputstream);
            String mkeyPath = pathConfig.getProperty(MASTERKEY_PATH);

			MASTERKEY_ABSOLUTE_PATH = mkeyPath;

        } catch (Exception e) {
			MASTERKEY_ABSOLUTE_PATH = DEFAULT_MASTERKEY_PATH;
			logger.error("加载master key配置文件失败，使用默认的master key路径：", MASTERKEY_ABSOLUTE_PATH);
        }
	}
	
	/**
	 * 
	 * @Description: 	根据key获取内容 
	 * @param key		键值
	 * @return 			内容
	 */
    public static String getValueBykey(String key) {
    	if(KeyLockUtils.getLock()) {
			try {
				String value = getProp().getProperty(key);
				return value;
			} catch (Exception e) {
                logger.error("获取密钥配置失败：", e);
			}
		}
        
        return null;
    }
    
    /**
	 * 
	 * @Description: 	根据key设置内容 
	 * @param key		键值
	 * @param value 	内容
	 */
    public static void setValueBykey(String key, String value) {
		if (hasPermission()) {
            Properties propConfig = getProp();
            propConfig.setProperty(key, value);
			try {
				FileOutputStream outputstream = new FileOutputStream(MASTERKEY_ABSOLUTE_PATH);
                propConfig.store(outputstream, "change key " + new Date());
				outputstream.close();
			} catch (FileNotFoundException e) {
				logger.error("set master key propertis failed : file not found:", e);
			} catch (IOException e) {
				logger.error("set master key propertis failed :", e);
			}
		} else {
			logger.error("设置master key失败：没有权限");
		}
    }

	/**
	 * 备份远程共享的master key，在设置key之前先做一次备份,备份文件后缀名为当前时间
	 */
	public static void backupMasterKeyProperties(){
		if(StringUtils.isBlank(MASTERKEY_ABSOLUTE_PATH)){
			InputStream inputstream = KeyPropertiesUtils.class.getClassLoader().getResourceAsStream(SensitiveInfoConstants.CIPHERPROP_PATH);
			Properties pathConfig = new Properties();
			try {
				pathConfig .load(inputstream);
			} catch (IOException e) {
				logger.error("backup master key properties file failed:" + e);
			}
			String mkeyPath = pathConfig.getProperty(MASTERKEY_PATH);

			MASTERKEY_ABSOLUTE_PATH = mkeyPath;
		}
		Date now = new Date();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		String backupPath = MASTERKEY_ABSOLUTE_PATH + "." + dateFormat.format(now);
		File srcFile = new File(MASTERKEY_ABSOLUTE_PATH);
		File outFile = new File(backupPath);
		InputStream is = null;
		OutputStream os = null;
		try {
			is = new FileInputStream(srcFile);
			os = new FileOutputStream(outFile);
			byte[] buf = new byte[512];
			int i;
			while ((i = is.read(buf)) != -1) {
				os.write(buf, 0, i);
			}
		} catch (FileNotFoundException e) {
			logger.error("backup remote key propertis failed : file not found:", e);
		} catch (IOException e) {
			logger.error("backup remote key propertis failed : ", e);
		} finally {
			try {
				is.close();
				os.close();
			} catch (IOException e) {
				logger.error("close iostream failed：", e);
			}
		}
	}

	/**
	 *
	 * @Description: 	(保证该只有SecurityKeysSupervise接口有修改权限
	 * @return 			是SecurityKeysSupervise调用返回true，否则返回false
	 * @author zyt
	 */
	private static boolean hasPermission(){
		StackTraceElement[] stackElements = Thread.currentThread().getStackTrace();
		if (stackElements != null) {
			for (StackTraceElement ste : stackElements) {
				if(StringUtils.containsIgnoreCase(ste.getClassName(), "SecurityKeysSupervise")){
					return true;
				}
			}
		}

		return false;
	}
}
